/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#include "ak_sbf.h"
#include "ak_mc.h"

/* =====================================================================
**	 Mc Operations:
*/
int 	McCc_Get(void * pMcCc, unsigned long long  key, int timeout, _t_cbentry	* pCbEntry)
{
	int 				ret;
	_t_SBF_CcCtx 	* 	pCcCtx;
	_t_SBF_CbNode 	* 	pCbNode;
	_t_mc_message		mcMsg;

	ret = -1;
	pCcCtx = (_t_SBF_CcCtx *)pMcCc;
	if(pCcCtx && pCbEntry &&(pCbEntry->cbProc)){
		pCbNode = SBF_Apply(pCcCtx, pCbEntry, timeout);
		if(pCbNode){
			/* Message Element */
			mcMsg.elem.type= _MC_SAP_INTER;
			mcMsg.elem.dir = _MSGELEM_REQ;
			mcMsg.elem.length= sizeof(_t_mc_message);
			mcMsg.elem.piggyback = pCbNode->ci.casId;
			
			/* Code & Expire */
			mcMsg.code 		= _MC_CMD_GET;
			mcMsg.expire 	= 0;

			/* Data */
			mcMsg.data.key	= key;

			/* Send Out */
			
			return 0;
		}
	}

	return -1;
}


int 	McCc_GetEx(void * pMcCc, unsigned long long key, int timeout, unsigned char * pBuf, int * lBuf)
{
	_t_SBF_CcCtx 	* 	pCcCtx;
	_t_SBF_CbNode 	* 	pCbNode;
	_t_mc_message		mcMsg;
	
	pCcCtx = (_t_SBF_CcCtx *)pMcCc;
	if(	pMcCc && pBuf && lBuf && (*lBuf > 0)){
		pCbNode = SBF_ApplyEx(pCcCtx, pBuf, lBuf,  timeout);
		if(pCbNode){
			/* Message Element */
			mcMsg.elem.type= _MC_SAP_INTER;
			mcMsg.elem.dir = _MSGELEM_REQ;
			mcMsg.elem.length= sizeof(_t_mc_message);
			mcMsg.elem.piggyback = pCbNode->ci.casId;
			
			/* Code & Expire */
			mcMsg.code 		= _MC_CMD_GET;
			mcMsg.expire 	= 0;

			/* Data */
			mcMsg.data.key	= key;

			/* Send Out */

			/* Now Let's Wait */
			#if 1
			SYS_SEM_B_TAKE(pCbNode->pWake, _WAIT_FOREVER);
			#endif
			/* When WakeUp, OutBuf & OutLen is Already Set */
			
			return 0;
		}
	}

	return -1;
}


int 	McCc_Del(void * 	pMcCc, unsigned long long key)
{
	_t_SBF_CcCtx 	* 	pCcCtx;
	_t_mc_message		mcMsg;
	
	pCcCtx = (_t_SBF_CcCtx *)pMcCc;
	if(	pMcCc ){
		/* Message Element */
		mcMsg.elem.type= _MC_SAP_INTER;
		mcMsg.elem.dir = _MSGELEM_REQ;
		mcMsg.elem.length= sizeof(_t_mc_message);
		mcMsg.elem.piggyback = 0;
		
		/* Code & Expire */
		mcMsg.code		= _MC_CMD_DEL;
		mcMsg.expire	= 0;
		
		/* Data */
		mcMsg.data.key	= key;
		
		/* Send Out */

		return 0;
	}

	return -1;
}

int 	McCc_Set(void *	pMcCc, unsigned long long key, int expire, unsigned char * pBuf, int lBuf)
{
	_t_SBF_CcCtx 	* 	pCcCtx;
	_t_mc_message		mcMsg;
	
	_t_sgbuf 			sgBuf[2];
	unsigned char 		zipBuf[_MC_MSG_MAXSZ + 1];

	pCcCtx = (_t_SBF_CcCtx *)pMcCc;
	if(	pMcCc && (lBuf > 0) && (lBuf< _MC_MSG_MAXSZ) ){
		/* Message Element */
		mcMsg.elem.type= _MC_SAP_INTER;
		mcMsg.elem.dir = _MSGELEM_REQ;
		mcMsg.elem.length= sizeof(_t_mc_message);
		mcMsg.elem.piggyback = 0;
		
		/* Code & Expire */
		mcMsg.code		= _MC_CMD_SET;
		if(expire < 0){
			expire = 0;
		}
		mcMsg.expire	= expire;
		
		/* Data */
		mcMsg.data.key	= key;
		
		sgBuf[0].SGBUF_PTR = (unsigned char *)(&(mcMsg));
		sgBuf[0].SGBUF_LEN= sizeof(_t_mc_message);

		/* Judge if Need Zip */
		if(lBuf >= _MC_MSG_ZIPSZ){
			mcMsg.data.dLen = _Mc_DataEnc(pBuf, zipBuf, lBuf);
			sgBuf[1].SGBUF_PTR = zipBuf;
		}else{
			mcMsg.data.dLen = mcMsg.data.rLen;
			sgBuf[1].SGBUF_PTR = pBuf;
		}
		mcMsg.data.rLen = lBuf;
		sgBuf[1].SGBUF_LEN = mcMsg.data.dLen;
		
		/* Send Out */

		return 0;
	}

	return -1;
}


void * 	McCc_Init(_t_cbentry * pCombine)
{
	_t_SBF_CcCtx * 	pCcCtx;
	
	pCcCtx = SYS_CALLOC(1, sizeof(_t_SBF_CcCtx));
	if(pCcCtx && pCombine && (pCombine->cbProc)){
		SBF_Init(pCcCtx);

		/* Add the Task of Cb, Should Set the Exec Part of the pCcCtx */
		pCombine->cbProc(pCombine->pArg, 
						 pCombine->lArg, 
						 pCcCtx);
		return pCcCtx;
	}

	return NULL;
}

